package com.android_map_app.services;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.LinkedList;

import org.json.JSONArray;
import org.json.JSONObject;

import android.app.Service;
import android.content.Intent;
import android.content.SharedPreferences;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;

import com.android_map_app.R;
import com.android_map_app.activities.MainActivity;
import com.android_map_app.activities.MapApplication;
import com.android_map_app.data.User;
import com.android_map_app.data.UserData;

public class UpdateService extends Service implements LocationListener {

	private static final String TAG = UpdateService.class.getSimpleName();
	public static final String ACTION_NEW_COORDINATES = "Map.NewCoordinates";
	private Updater updater;
	private LocationManager locationManager;
	private String provider = LocationManager.GPS_PROVIDER;
	private UserData usersData;
	private User user;
	private MapApplication mapApplication;
	private SharedPreferences mPrefs;
	
	@Override
	public IBinder onBind(Intent intent) {
		return null;
	}

	@Override
	public void onCreate() {
		super.onCreate();
		Log.d(TAG, "onCreated");
		usersData = UserData.getInstance();
		user = usersData.getUser();
		
		mapApplication = (MapApplication) getApplication();
		mPrefs = getSharedPreferences(MainActivity.USER_PREF, MODE_PRIVATE);
		
		updater = new Updater();
		locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
		locationManager.requestLocationUpdates(provider, 1000, 1, this);
		Location lastLocation = locationManager.getLastKnownLocation(provider);
		if (lastLocation != null) {
			onLocationChanged(lastLocation);
		}
	}

	@Override
	public synchronized void onStart(Intent intent, int startId) {
		super.onStart(intent, startId);
		Log.d(TAG, "onStarted");
		locationManager.requestLocationUpdates(provider, 1000, 1, this);
		if (!updater.isRunning()) {
			updater.start();
			mapApplication.setServiceRunning(true);
		}
	}
	
	@Override
	public synchronized void onDestroy() {
		super.onDestroy();
		Log.d(TAG, "onDestroyed");
		locationManager.removeUpdates(this);
		if (updater.isRunning()) {
			updater.interrupt();
			updater.setRunning(false);
		}
		mapApplication.setServiceRunning(false);
		//to ease garbage collector's work
		updater = null;
	}

	private class Updater extends Thread {
		private static final long INTERVAL = 1000;
		private boolean isRunning = false;
		
		public Updater() {
			super("Updater");
		}
		
		@Override
		public void run() {
			isRunning = true;
			while(isRunning) {
				try{
					Log.d(TAG, "tick; activeroup - " + mPrefs.getString("activeGroup", ""));
					updateUsersData();
					sendBroadcast(new Intent(ACTION_NEW_COORDINATES)); //notify changes
					Thread.sleep(INTERVAL);
				} catch (InterruptedException e) {
					isRunning = false;
				}
			}
		}

		public synchronized boolean isRunning() {
			return isRunning;
		}

		public synchronized void setRunning(boolean isRunning) {
			this.isRunning = isRunning;
		}
		
		private void updateUsersData() {
			JSONObject response;
			try {
				Location loc = user.getLocation();
				double longitude = 0;
				double latitude = 0;
				if (loc != null) {
					longitude = loc.getLongitude();
					latitude = loc.getLatitude();
				}
				URL updateUrl = new URL("http://" 
						+ getBaseContext().getString(R.string.server_name)
						+ "/update?action=update&longitude=" + longitude
						+ "&latitude=" + latitude + "&idCode=" + mPrefs.getString("idCode", ""));
				BufferedReader bfr = new BufferedReader(
						new InputStreamReader(updateUrl.openStream()));
				response = new JSONObject(bfr.readLine());
				bfr.close();
				if (((String) response.get("statusMessage")).equals("success")) {
					JSONArray groups = response.getJSONArray("groups");
					JSONArray responseUsers = response.getJSONArray("members");
					for (int i = 0; i < groups.length(); i++) {
						LinkedList<User> users = new LinkedList<User>();
						String[] members = ((String) responseUsers.get(i)).split("\\;");
						for (String member : members) {
							String[] userData = member.split("\\,");
							if (!userData[0].equals(mPrefs.getString("username", ""))) {
								users.add(new User(userData[0], userData[1], userData[2]));
							}
						}
						usersData.setUsersToGroup(groups.get(i).toString(), users);
					}
				} else {
					throw new Exception();
				}
			} catch (Exception e) {
//				Log.d(TAG, e.getMessage());
				//TODO: remove this:
				e.printStackTrace();
				isRunning = false;
				stopService(new Intent(UpdateService.this, UpdateService.class));
			}
		}
	}

	@Override
	public void onLocationChanged(Location location) {
		Log.d(TAG, "location changed");
		user.setLocation(location);
	}

	@Override
	public void onProviderDisabled(String provider) {
		if (this.provider.equals(provider)) {
			Log.d(TAG, "provider disabled");
			locationManager.removeUpdates(this);
		}
		
	}

	@Override
	public void onProviderEnabled(String provider) {
		if (this.provider.equals(provider)) {
			Log.d(TAG, "provider enabled");
			locationManager.requestLocationUpdates(provider, 1000, 1, this);
		}
	}

	@Override
	public void onStatusChanged(String provider, int status, Bundle extras) {
		// TODO Auto-generated method stub
	}
}
